#!/usr/bin/env python
"""Launcher class to avoid circular imports"""
import os, sys, random, pygame, getopt
from OpenGL.GL import *
from OpenGL.GLU import *
import game, vecmath, camera, starfield, particles, ai, net, gl
from mission import mission
from vessels import *
import vessels
from pygame.locals import *

DISPLAY_SIZE = (1024, 700)
DISPLAY_FLAGS = DOUBLEBUF | OPENGL | HWSURFACE
FPS = 30.0
F_DELTA = FPS / 1000.0 # to calculate time-based deltas
clock = None
_running = 1
_jit = 1 # flag to enable jit via psyco
_profile = 0 # flag to enable profiling via hotshot
_player_class = 'colonial.Viper' # default player class
_bots_cylons = 8 # number of cylons controlled by ia
_bots_humans = 11 # number of humans controller by ia
_multiplayer_protocol = 0 # server or client infrastructure to loop in

def process_events():
    """Processess mouse and kb events for the main ui"""
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit(0)
        elif event.type == KEYUP:
            if event.key == K_ESCAPE:
                global _running
                _running = 0
            if event.key == K_KP_PLUS:
                game.zoom += 0.1
            if event.key == K_KP_MINUS:
                game.zoom -= 0.1
            if event.key == K_z:
                game.cam.zoom_enabled = not game.cam.zoom_enabled
                game.zoom = 1
            if event.key == K_r:
                init_players()
                init_mission()
            if event.key == K_i:
                for ship in game.ships:
                    try:
                        game.debug(ship.controller.target.__str__())
                    except:
                        pass

def startup():
    """Inites the game to a initial state
    Creates the display and populates the 'game' objects"""
    game.init(DISPLAY_SIZE, DISPLAY_FLAGS)
    
    gl.glInit(DISPLAY_SIZE[0], DISPLAY_SIZE[1])
    
    game.particles = particles.ParticleSystem(5000)
    game.ships = gl.GLGroup()
    game.dimensions = Rect((0, 0), DISPLAY_SIZE)
    game.stars = starfield.Starfield(game.dimensions)
    game.bullets = gl.GLGroup()
    game.font = gl.GLFont()
    
    init_players()
    init_mission()

def init_mission():
    ptype = _player_class.split('.') # guess what character the players chooses to play
    pclass = None    
    try:
        pclass = vessels.__dict__[ptype[0]].__dict__[ptype[1].title()]
    except KeyError:
        print "Wrong type of ship " + _player_class
        sys.exit(1)
    
    game.mission = mission.Test(pclass, vessels.cylon.Raider) #TODO guess team2 class

def init_players():
    game.bullets.empty()
    game.ships.empty()
    ptype = _player_class.split('.') # guess what character the players chooses to play
    pclass = None
    
    try:
        pclass = vessels.__dict__[ptype[0]].__dict__[ptype[1].title()]
    except KeyError:
        print "Wrong type of ship " + _player_class
        sys.exit(1)
    
    if ptype[0] == 'cylon':
        player = pclass()
        player.position = [-1000 - random.random() * 1000, -1000 - random.random() * 1000]
    if ptype[0] == 'colonial':
        player = pclass()
        player.position = [1000 + random.random() * 1000, 1000 + random.random() * 1000]
    
    game.cam = camera.Camera(player) # set the camera to the player
    game.ships.add(player) # register the player's ship
    
    if not _multiplayer_protocol:
        for i in xrange(_bots_humans):
            e = colonial.Viper(ai.Simple)
            e.position = [1000 + random.random() * 1000, 1000 + random.random() * 1000]
            game.ships.add(e)
            
        for i in xrange(_bots_cylons):
            e = cylon.Raider(ai.Simple)
            e.position = [-1000 + random.random() * -1000, -1000 + random.random() * -1000]
            game.ships.add(e)
    else:
        player.controller = net.NetPlayerController(player)
        _multiplayer_protocol.player = player
        _multiplayer_protocol.start()

def main_loop():
    """Will iterate while _running is true,
    processing events, drawing and updating the game state"""
    #proxy methods
    groups = game.update_groups
    redraw = game.redraw
    ticks = pygame.time.get_ticks
    tick = clock.tick
    time = pygame.time.get_ticks() + 1000*60
    while(_running):
        delta = tick(FPS) * F_DELTA
        game.delta = delta
        process_events()
        if _multiplayer_protocol:
            _multiplayer_protocol.update()
        groups(delta)
        redraw()
        if (ticks() % 1000) < 100 :
            game.fpscounter = ('fps:' + str(clock.get_fps()) + ' || x' + str(delta))
        #if(pygame.time.get_ticks() > time): # profile for 60 seconds
        #    break
    if _multiplayer_protocol:
        _multiplayer_protocol.stop()

def run_profile():
    """Performs a full profile of the application"""
    import hotshot, hotshot.stats, test.pystone
    prof = hotshot.Profile("pyship.prof") # file to store the results
    benchtime = prof.run('main_loop()') # run the method
    prof.close() # done
    stats = hotshot.stats.load("pyship.prof") # load the results
    stats.strip_dirs() 
    stats.sort_stats('time', 'calls') # sort by time invested on each method
    stats.print_stats(20)
    
def usage():
    print '''Usage: python main.py [options]
    Options:
        -h, --help: Shows this message
        -p, --profile: Runs the game through a profiler and shows the results on
                       exit
        -n, --no-optimize: Skips the jit compilation with psyco (use if you have
                           problems running psyco)
        -a S, --play-as=S: Team and ship to play as, for example
                            --a colonial.viper or --play-as=cylon.raider
        -c N, --cylons=N: Number of cylon bots to add to the game
        -h N, --colonials=N: Number of colonial bots to add to the game
	-f, --fullscreen: Runs the game in fullscreen mode
	-s WxH, --screen-size=WxH: sets the window size
	-j ip:port, --join-game=ip:port: tries to join a game instead launching
                                         local play'''
    sys.exit(0)

if (__name__ ==  '__main__'):
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hpnc:l:a:fs:j:",\
                                   ["help", "profile", "no-optimize",\
                                    "cylons=", "colonials=", "play-as=",\
                                    "fullscreen", "screen-size=", 'join-game='])
    except getopt.GetoptError:
        print 'Opciones no reconocidas'
        usage()
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            usage()
        elif opt in ('-p', '--profile'):
            _profile = 1
        elif opt in ('-n', '--no-optimize'):
            _jit = 0
        elif opt in ('-l', '--colonials'):
            _bots_humans = arg
        elif opt in ('-e', '--cylons'):
            _bots_cylons = arg
        elif opt in ('-a', '--play-as'):
            _player_class = arg
        elif opt in ('-f', '--fullscreen'):
            DISPLAY_FLAGS = DISPLAY_FLAGS | FULLSCREEN
        elif opt in ('-s', '--screen-size'):
            r = arg.lower().split('x')
            DISPLAY_SIZE = int(r[0]), int(r[1])
        elif opt in ('-j', '--join-game'):
            args = arg.split(':')
            mp_ip = args[0]
            if len(args) == 2:
                _multiplayer_protocol = net.ClientProtocol(mp_ip, port = args[1])
            else:
                _multiplayer_protocol = net.ClientProtocol(mp_ip)

    if _jit:
        try:
            import psyco
            #psyco.log()
            psyco.full()
        except ImportError, message:
            print message

    #_multiplayer_protocol = net.ClientProtocol('127.0.0.1')

    pygame.init()
    #from OpenGL import error
    #error.ErrorChecker.registerChecker(lambda:None)
    
    clock = pygame.time.Clock()
    pygame.display.set_caption('ship3 python rewrite')
    pygame.mouse.set_visible(0)
    
    startup()
    
    if _profile:
        run_profile()
    else:
        main_loop()
